#include "StdAfx.h"
#include "BaseWindow.h"

CBaseWindow::CBaseWindow(void):m_hWnd(NULL)
{
	hidden = FALSE;

	SetLayeredWindowAttributes = NULL;
	HINSTANCE hInstDll = LoadLibrary(_T("User32.DLL")); 
	if(hInstDll)
	{ 
		SetLayeredWindowAttributes=(SETLAYEREDWINDOWATTRIBUTES)GetProcAddress(hInstDll, "SetLayeredWindowAttributes");
		FreeLibrary(hInstDll); 
	}
}
void CBaseWindow::SetTransparent(int rate)
{
	rate = 255 * rate / 100;
	if(SetLayeredWindowAttributes)
	{
		SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)^0x80000);
		SetLayeredWindowAttributes(m_hWnd,0,rate,2);
	}
}

CBaseWindow::~CBaseWindow(void)
{
}

BOOL CBaseWindow::RegisterClass(LPCTSTR lpszClass, HINSTANCE hInst)
{
	WNDCLASSEX wc;

	if(!GetClassInfoEx( hInst, lpszClass, & wc))
	{
		GetWndClassEx(wc);

		wc.hInstance     = hInst;
		wc.lpszClassName = lpszClass;

		if (!::RegisterClassEx(& wc))
			return FALSE;
	}

	return TRUE;
}
void CBaseWindow::GetWndClassEx(WNDCLASSEX& wc)
{
	ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.lpfnWndProc = CBaseWindow::WindowProc;
    wc.style = CS_DBLCLKS | CS_DROPSHADOW;
    wc.cbSize = sizeof (WNDCLASSEX);

    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszMenuName = NULL;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
}

BOOL CBaseWindow::CreateEx(
		DWORD dwExStyle,
		LPCTSTR lpszClass, LPCTSTR lpszName, DWORD dwStyle,
		int nX, int nY, int cx, int cy,
		HWND hParent,
		HMENU hMenu,
		HINSTANCE hInst
	)
{
	m_hInst = hInst;

	if(!RegisterClass(lpszClass, hInst))
		return FALSE;

	m_hWnd = ::CreateWindowEx(
		dwExStyle, lpszClass, lpszName, dwStyle,
		nX, nY, cx, cy,
		hParent, hMenu, hInst,
		(LPVOID)this);

	return m_hWnd != NULL;
}

LRESULT CALLBACK CBaseWindow::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	CBaseWindow* pBaseWindow = NULL;

	if(uMsg == WM_NCCREATE)
	{
		LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>( lParam );

		pBaseWindow = reinterpret_cast<CBaseWindow*>(lpcs->lpCreateParams);
		pBaseWindow->OnNcCreate(lpcs);

		SetWindowLong(hwnd, GWL_USERDATA, (LONG) pBaseWindow);
	}
	else
	{
		pBaseWindow = (CBaseWindow*)::GetWindowLong(hwnd, GWL_USERDATA);
	}

	if(pBaseWindow)
		return pBaseWindow->WndProc(hwnd, uMsg, wParam, lParam);
	
	return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
}
WPARAM CBaseWindow::MsgLoop()
{
	MSG msg;

	while ( ::GetMessage( & msg, NULL, 0, 0 ) )
	{
		::TranslateMessage( & msg );
		::DispatchMessage( & msg );
	}

	return msg.wParam;
}

int CBaseWindow::OnNcCreate(LPCREATESTRUCT lpcs)
{
	return 0;
}

LRESULT CBaseWindow::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{
	case WM_COMMAND:
		OnCommand((HWND)lParam, LOWORD(wParam), HIWORD(wParam));
		return 0;

	case WM_CREATE:
		OnCreate(( LPCREATESTRUCT)lParam);
		break;

	//case WM_PAINT:
	//	{
	//		PAINTSTRUCT ps;
	//		BeginPaint(m_hwnd, & ps);
	//		OnPaint(ps.hdc);
	//		EndPaint(m_hwnd, & ps);
	//	}
	//	return 0;

	//case WM_DESTROY:
	//	OnDestroy();
	//	return 0;

	case WM_CLOSE:
		OnClose();
		return 0;

	default:
		break;
	}

	return WndProcExt(hwnd, uMsg, wParam, lParam);
}
LRESULT CBaseWindow::WndProcExt(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int CBaseWindow::OnCreate(LPCREATESTRUCT lpcs)
{
	return 0;
}

void CBaseWindow::OnClose()
{
	PostQuitMessage(0);
}

int CBaseWindow::OnCommand(HWND hWnd, WORD wID, WORD wNotifyCode)
{
	switch(wID)
	{
	case IDOK:
		PostQuitMessage(0);
	default:
		break;
	}
	return OnCommandExt(hWnd, wID, wNotifyCode);
}
int CBaseWindow::OnCommandExt(HWND hWnd, WORD wID, WORD wNotifyCode)
{
	return 0;
}
BOOL CBaseWindow::CenterWindow(DWORD dwFlags)
{
	RECT rtWindow = {0};  
	RECT rtContainer = {0};  

	GetWindowRect(m_hWnd,&rtWindow);  
	rtWindow.right -= rtWindow.left;  
	rtWindow.bottom -= rtWindow.top;  

	switch(dwFlags)  
	{  
	case CW_SCREEN:  
		rtContainer.right = GetSystemMetrics(SM_CXSCREEN);  
		rtContainer.bottom = GetSystemMetrics(SM_CYSCREEN);  
		break;  
	case CW_WORKAREA:  
		SystemParametersInfo(SPI_GETWORKAREA,0,&rtContainer,0);  
		break;  
	}  

	return SetWindowPos(m_hWnd,NULL,(rtContainer.right - rtWindow.right) / 2,(rtContainer.bottom - rtWindow.bottom) / 2,0,0,SWP_NOSIZE);  
}


Bitmap* CBaseWindow::LoadPng(unsigned short pName, LPCTSTR pType)
{
	Bitmap* r = NULL;
	HGLOBAL m_hBuffer;

	HRSRC hResource = ::FindResource(m_hInst, MAKEINTRESOURCE(pName), pType);
	if (!hResource)
		return NULL;	

	DWORD imageSize = ::SizeofResource(m_hInst, hResource);
	if (!imageSize)
		return NULL;

	const void* pResourceData = ::LockResource(::LoadResource(m_hInst, hResource));
	if (!pResourceData)
		return NULL;

	m_hBuffer  = ::GlobalAlloc(GMEM_MOVEABLE, imageSize);
	if (m_hBuffer)
	{
		void* pBuffer = ::GlobalLock(m_hBuffer);
		if (pBuffer)
		{
			CopyMemory(pBuffer, pResourceData, imageSize);

			IStream* pStream = NULL;
			if (::CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream) == S_OK)
			{
				r = Bitmap::FromStream(pStream);
				pStream->Release();
				if (r->GetLastStatus() != Gdiplus::Ok)
					r = NULL;
			}
			::GlobalUnlock(m_hBuffer);
		}
		::GlobalFree(m_hBuffer);
		m_hBuffer = NULL;
	}
	return r;
}

int CBaseWindow::Msgbox(LPCTSTR pMsg, LPCTSTR pTitle, UINT uType)
{
	return MessageBox(m_hWnd, pMsg, pTitle, uType);
}

void CBaseWindow::Show(BOOL show)
{
	if(show)
	{
		ShowWindow(m_hWnd, SW_SHOW);
		hidden = FALSE;
	}
	else
	{
		hidden = TRUE;
		ShowWindow(m_hWnd, SW_HIDE);
	}
}
void CBaseWindow::Toggle()
{
	Show(hidden);
}
